#include <vtkActor.h>
#include <vtkCallbackCommand.h>
#include <vtkCamera.h>
#include <vtkDataSetMapper.h>
#include <vtkExtractGeometry.h>
#include <vtkHexahedron.h>
#include <vtkIdList.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkPlane.h>
#include <vtkPlaneWidget.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkUnstructuredGrid.h>

// 全局变量
vtkSmartPointer<vtkExtractGeometry> extractGeometry;
vtkSmartPointer<vtkRenderer> renderer;

// 回调函数，当平面控件被移动时调用
void PlaneCallback(vtkObject* caller, long unsigned int eventId, void* clientData, void* callData)
{
    auto planeWidget = static_cast<vtkPlaneWidget*>(caller);
    auto plane = static_cast<vtkPlane*>(clientData);
    
    // 从平面控件获取当前的平面参数
    planeWidget->GetPlane(plane);
    
    // 更新提取几何的隐式函数
    extractGeometry->SetImplicitFunction(plane);
    
    // 强制重新渲染
    renderer->GetRenderWindow()->Render();
}

// 创建一个简单的立方体网格
vtkSmartPointer<vtkUnstructuredGrid> CreateCubeGrid()
{
    auto grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
    auto points = vtkSmartPointer<vtkPoints>::New();
    
    // 创建一个3x3x3的立方体网格
    int dims[3] = {101, 101, 101}; // 4个点在每个方向上，创建3x3x3=27个立方体
    
    // 添加点
    for (int k = 0; k < dims[2]; k++)
    {
        for (int j = 0; j < dims[1]; j++)
        {
            for (int i = 0; i < dims[0]; i++)
            {
                points->InsertNextPoint(i * 2.0, j * 2.0, k * 2.0);
            }
        }
    }
    
    grid->SetPoints(points);
    
    // 创建立方体单元（六面体）
    for (int k = 0; k < dims[2] - 1; k++)
    {
        for (int j = 0; j < dims[1] - 1; j++)
        {
            for (int i = 0; i < dims[0] - 1; i++)
            {
                auto hex = vtkSmartPointer<vtkHexahedron>::New();
                
                // 定义立方体的8个顶点（按VTK六面体顶点顺序）
                int base = k * dims[0] * dims[1] + j * dims[0] + i;
                hex->GetPointIds()->SetId(0, base);
                hex->GetPointIds()->SetId(1, base + 1);
                hex->GetPointIds()->SetId(2, base + 1 + dims[0]);
                hex->GetPointIds()->SetId(3, base + dims[0]);
                hex->GetPointIds()->SetId(4, base + dims[0] * dims[1]);
                hex->GetPointIds()->SetId(5, base + 1 + dims[0] * dims[1]);
                hex->GetPointIds()->SetId(6, base + 1 + dims[0] + dims[0] * dims[1]);
                hex->GetPointIds()->SetId(7, base + dims[0] + dims[0] * dims[1]);
                
                grid->InsertNextCell(hex->GetCellType(), hex->GetPointIds());
            }
        }
    }
    
    return grid;
}

int main()
{
    // 创建非结构化网格
    auto grid = CreateCubeGrid();
    
    // 创建平面对象
    auto plane = vtkSmartPointer<vtkPlane>::New();
    plane->SetOrigin(3.0, 3.0, 3.0);  // 平面原点
    plane->SetNormal(1.0, 0.0, 0.0);  // 平面法向量
    
    // 创建几何提取器
    extractGeometry = vtkSmartPointer<vtkExtractGeometry>::New();
    extractGeometry->SetInputData(grid);
    extractGeometry->SetImplicitFunction(plane);
    extractGeometry->ExtractInsideOn();  // 提取平面法向量方向一侧的单元
    extractGeometry->ExtractBoundaryCellsOff();  // 不提取边界单元
    
    // 创建映射器
    auto mapper = vtkSmartPointer<vtkDataSetMapper>::New();
    mapper->SetInputConnection(extractGeometry->GetOutputPort());
    
    // 创建演员
    auto actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);
    actor->GetProperty()->SetColor(0.8, 0.2, 0.2);  // 红色
    actor->GetProperty()->SetOpacity(0.8);
    actor->GetProperty()->EdgeVisibilityOn();  // 显示边缘
    actor->GetProperty()->SetEdgeColor(0.0, 0.0, 0.0);  // 黑色边缘
    
    // 创建渲染器
    renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(actor);
    renderer->SetBackground(0.1, 0.1, 0.2);  // 深蓝色背景
    
    // 创建渲染窗口
    auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(renderer);
    renderWindow->SetSize(800, 600);
    renderWindow->SetWindowName("VTK Plane Widget Clipping Demo");
    
    // 创建交互器
    auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactor->SetRenderWindow(renderWindow);
    
    // 创建平面控件
    auto planeWidget = vtkSmartPointer<vtkPlaneWidget>::New();
    planeWidget->SetInteractor(interactor);
    planeWidget->SetInputData(grid);
    planeWidget->SetOrigin(3.0, 3.0, 3.0);
    planeWidget->SetNormal(1.0, 0.0, 0.0);
    planeWidget->SetResolution(10);  // 平面控件的分辨率
    planeWidget->SetRepresentationToOutline();  // 显示为轮廓
    planeWidget->PlaceWidget();
    
    // 设置平面控件的外观
    planeWidget->GetPlaneProperty()->SetColor(1.0, 1.0, 0.0);  // 黄色
    planeWidget->GetPlaneProperty()->SetOpacity(0.5);
    planeWidget->GetHandleProperty()->SetColor(0.0, 1.0, 0.0);  // 绿色手柄
    planeWidget->GetSelectedHandleProperty()->SetColor(1.0, 0.0, 1.0);  // 选中时紫色
    
    // 创建回调函数
    auto callback = vtkSmartPointer<vtkCallbackCommand>::New();
    callback->SetCallback(PlaneCallback);
    callback->SetClientData(plane);
    
    // 连接回调函数到平面控件
    planeWidget->AddObserver(vtkCommand::InteractionEvent, callback);
    
    // 启用平面控件
    planeWidget->On();
    
    // 设置相机位置以获得更好的视角
    renderer->GetActiveCamera()->SetPosition(15, 15, 15);
    renderer->GetActiveCamera()->SetFocalPoint(3, 3, 3);
    renderer->GetActiveCamera()->SetViewUp(0, 0, 1);
    renderer->ResetCameraClippingRange();
    
    // 开始渲染和交互
    renderWindow->Render();
    
    std::cout << "VTK平面裁剪演示程序" << std::endl;
    std::cout << "操作说明：" << std::endl;
    std::cout << "- 拖拽黄色平面来改变裁剪位置" << std::endl;
    std::cout << "- 拖拽绿色手柄来调整平面方向" << std::endl;
    std::cout << "- 鼠标左键：旋转视角" << std::endl;
    std::cout << "- 鼠标右键：缩放" << std::endl;
    std::cout << "- 鼠标中键：平移" << std::endl;
    std::cout << "- 按 'q' 或关闭窗口退出" << std::endl;
    
    interactor->Start();
    
    return 0;
}